package com.robot.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.google.gson.JsonObject;
import com.robot.common.enums.ResponseEnum;
import com.robot.common.enums.TimeTypeEnum;
import com.robot.common.exception.BusinessException;
import com.robot.common.utils.DateSplitUtil;
import com.robot.dao.dto.LargeMarketDTO;
import com.robot.dao.entity.Integral;
import com.robot.dao.entity.IntegralLog;
import com.robot.dao.mapper.CompanyMapper;
import com.robot.dao.mapper.IntegralLogMapper;
import com.robot.dao.mapper.UserMapper;
import com.robot.dao.vo.IconVO;
import com.robot.dao.vo.LargeMarketVO;
import com.robot.service.IntegralLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import springfox.documentation.spring.web.json.Json;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IntegralLogServiceImpl implements IntegralLogService {

    @Autowired
    private IntegralLogMapper integralLogMapper;

    @Autowired
    private UserMapper userMapper;


    @Autowired
    private CompanyMapper companyMapper;

    public Long integralUsage(LargeMarketDTO largeMarketDTO) {
        Long integralId = this.checkIntegralId(largeMarketDTO);
        Long score = integralLogMapper.integralUsage(integralId);
        if(ObjectUtils.isEmpty(score)){
            score=0L;
        }
        return score;

    }

    @Override
    public LargeMarketVO integralTrend(LargeMarketDTO largeMarketDTO) throws ParseException {
        this.checkIntegralId(largeMarketDTO);
        List<String> dateList = this.dateCount(largeMarketDTO);
        LargeMarketDTO largeMarketDTOReal=this.buildFillDateReq(largeMarketDTO);
        List<IconVO> valueList = integralLogMapper.integralTrend(largeMarketDTOReal);
        log.info("积分消耗数据库查询。。。。。{}", JSONObject.toJSON(valueList));
        List<Integer> list = this.buildLargeMarketVO(dateList, valueList);
        log.info("时间积分对应map。。。。。{}", JSONObject.toJSON(list));
        LargeMarketVO largeMarketVO=LargeMarketVO.builder()
                .dateList(dateList)
                .valueList(list)
                .build();
        log.info("积分消耗。。。。。{}", JSONObject.toJSON(largeMarketVO));
        return largeMarketVO;
    }

    @Override
    public LargeMarketVO integralFrequency(LargeMarketDTO largeMarketDTO) throws ParseException {
        this.checkIntegralId(largeMarketDTO);
        List<String> dateList = this.dateCount(largeMarketDTO);
        LargeMarketDTO largeMarketDTOReal = this.buildFillDateReq(largeMarketDTO);
        List<IconVO> valueList = integralLogMapper.integralFrequency(largeMarketDTOReal);
        log.info("使用人数数据库查询。。。。。{}", JSONObject.toJSON(valueList));
        List<Integer> list = this.buildLargeMarketVO(dateList, valueList);
        log.info("时间积分对应map。。。。。{}", JSONObject.toJSON(list));
        LargeMarketVO largeMarketVO = LargeMarketVO.builder()
                .dateList(dateList)
                .valueList(list)
                .build();
        log.info("使用人数。。。。。{}", JSONObject.toJSON(largeMarketVO));
        return largeMarketVO;

    }


    private Long checkIntegralId(LargeMarketDTO largeMarketDTO) {
        Long integralId = largeMarketDTO.getIntegralId();
        if (ObjectUtils.isEmpty(integralId)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请传入积分账户Id！");
        }
        return integralId;

    }



    /**
     * 根据年月日填补时间到时分秒，并获取时间格式
     *
     * @param largeMarketDTO
     *
     * @return
     *
     * @throws ParseException
     */
    private LargeMarketDTO buildFillDateReq(LargeMarketDTO largeMarketDTO) throws ParseException {
        Date dateStart;
        Date dateEnd;

        String dimension = largeMarketDTO.getDimension();
        if (dimension.equals(TimeTypeEnum.YEAR.getCode())) {
            dateStart = new SimpleDateFormat("yyyy").parse(largeMarketDTO.getStartTime());
            dateEnd = new SimpleDateFormat("yyyy").parse(largeMarketDTO.getEndTime());
            largeMarketDTO.setStartTime(DateSplitUtil.getYearStart(dateStart));
            largeMarketDTO.setEndTime(DateSplitUtil.getNextYearStart(dateEnd));
            largeMarketDTO.setDimension(TimeTypeEnum.YEAR.getReal());

        } else if (dimension.equals(TimeTypeEnum.MONTH.getCode())) {
            dateStart = new SimpleDateFormat("yyyy-MM").parse(largeMarketDTO.getStartTime());
            dateEnd = new SimpleDateFormat("yyyy-MM").parse(largeMarketDTO.getEndTime());
            largeMarketDTO.setStartTime(DateSplitUtil.getMonthStart(dateStart));
            largeMarketDTO.setEndTime(DateSplitUtil.getNextMonthStart(dateEnd));
            largeMarketDTO.setDimension(TimeTypeEnum.MONTH.getReal());

        } else if (dimension.equals(TimeTypeEnum.DATE.getCode())) {
            dateStart = new SimpleDateFormat("yyyy-MM-dd").parse(largeMarketDTO.getStartTime());
            dateEnd = new SimpleDateFormat("yyyy-MM-dd").parse(largeMarketDTO.getEndTime());
            largeMarketDTO.setStartTime(DateSplitUtil.getTodayStart(dateStart));
            largeMarketDTO.setEndTime(DateSplitUtil.getNextDayStart(dateEnd));
            largeMarketDTO.setDimension(TimeTypeEnum.DATE.getReal());

        } else if (dimension.equals(TimeTypeEnum.WEEK.getCode())) {
            dateStart = new SimpleDateFormat("yyyy-MM-dd").parse(largeMarketDTO.getStartTime());
            dateEnd = new SimpleDateFormat("yyyy-MM-dd").parse(largeMarketDTO.getEndTime());
            largeMarketDTO.setStartTime(DateSplitUtil.getTodayStart(dateStart));
            largeMarketDTO.setEndTime(DateSplitUtil.getNextDayStart(dateEnd));

        } else {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "无法识别的时间类型！");
        }
        return largeMarketDTO;

    }


    /**
     * 根据起始日期和标识获取时间分割
     *
     * @param largeMarketDTO
     * @return
     * @throws Exception
     */
    private List<String> dateCount(LargeMarketDTO largeMarketDTO) {
        //开始时间
        String startTime = largeMarketDTO.getStartTime();
        //结束时间
        String endTime = largeMarketDTO.getEndTime();
        //时间标识（年/月/日/周）
        String dimension = largeMarketDTO.getDimension();

        if (StringUtil.isEmpty(startTime) || StringUtil.isEmpty(endTime)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请传入起始时间");
        }
        if (StringUtil.isEmpty(dimension)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请传入时间选择类型");
        }

        List<String> stringList = new ArrayList<>();
        //根据年月日周算出时间间隔数
        try {
            if (dimension.equals(TimeTypeEnum.YEAR.getCode())) {
                stringList = DateSplitUtil.getYearBetweenDate(startTime, endTime);
            } else if (dimension.equals(TimeTypeEnum.MONTH.getCode())) {
                stringList = DateSplitUtil.getMonthBetweenDate(startTime, endTime);
            } else if (dimension.equals(TimeTypeEnum.DATE.getCode())) {
                stringList = DateSplitUtil.findEveryDay(startTime, endTime);
            } else if (dimension.equals(TimeTypeEnum.WEEK.getCode())) {
                stringList = DateSplitUtil.getWeekBetweenDates(startTime, endTime);
            }
        } catch (Exception e) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "传入的日期类型与日期不匹配请检查！");
        }
        return stringList;
    }


    private List<Integer> buildLargeMarketVO(List<String> dateList, List<IconVO> valueList){
        //横坐标时间转换map
        Map<String, Integer> dateMap = dateList.stream()
                .collect(Collectors.toMap(
                        // 将List中的String作为Map的键
                        s -> s,
                        // 将Map的值初始化为0
                        s -> 0,
                        // 如果有重复的键，则使用后面的值覆盖前面的值
                        (existing, replacement) -> existing
                ));
        log.info("横坐标时间日期转换。。。。。");

        //数据库中积分值转换map
        Map<String, IconVO> valueMap = valueList.stream()
                .collect(Collectors.toMap(IconVO::getTimes, obj -> obj));
        log.info("纵坐标值转换。。。。。");
        List<Integer> list=new ArrayList<>();

        for (Map.Entry<String, Integer> entry : dateMap.entrySet()) {
            String date = entry.getKey();
            if (ObjectUtils.isNotEmpty(valueMap.get(date))) {
                list.add(valueMap.get(date).getOrdinateVal());
            }else{
                list.add(0);
            }

        }
        return list;




    }


}
